﻿using System;
using System.IO;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using BoardAppUtil.Util;
using System.Configuration;



namespace BoardAppUtil.Util
{
    public class GalleryManager
    {
        //protected static ILog EventLog = LogManager.GetLogger("EventLog");
        //protected static ILog ErrorLog = LogManager.GetLogger("ErrorLog");

        #region Constants

        /// <summary>
        /// Folder path for a specific Image type should be in the following format
        /// {0} - Root path from the config file
        /// {1} - Image Type Name
        /// {2} - Id (PRIMARY KEY)
        /// </summary>
        private const string IMAGE_PATH = @"{0}/{1}/{2}.jpg";
        private const string IMG_PATH = "{0}\\{1}.jpg";
        private const string IMG_PATH_UP = "{0}{1}\\{2}.jpg";

        /// <summary>
        /// Folder path for the unknown image type should be in the following format
        /// {0} - Root path from the config file
        /// {1} - Image Type Name
        /// </summary>
        private const string UNKNOWN_IMAGE_PATH = @"{0}/{1}/{1}.jpg";

        /// <summary>
        /// This is the root path that is the Gallery folder path taken from the config file
        /// </summary>
        private static readonly string ROOT_PATH = ""; //Settings.Settings.ImageGalleryPath;
        
        #endregion

        #region Gallery Operations
        
        /// <summary>
        /// Gets the image for specified image type and entity id.
        /// If the image does not exist it will return the default 
        /// image for specified image type
        /// </summary>
        /// <param name="imageType">Image Type</param>
        /// <param name="entityId">Entity Id</param>
        /// <returns>Virtual Path of the image</returns>
        /// 
        public static string GetImage(ImageType imageType, int entityId)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_GetImage, EventStatus.Entry.ToString(), imageType.ToString(), entityId));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_GetImage, EventStatus.Entry.ToString(), imageType.ToString(), entityId));

            //GetImageVirtualPath(imageType, entityId);
            //string imagePath = imageType + "\\" + entityId + ".jpg";   
            string imagePath = string.Format(IMG_PATH, imageType, entityId);

            //if (!FileExist(imagePath))
            //{
            //    imagePath = GetUnknownImagePath(imageType);
            //}
            //EventLog.Info(String.Format(Resources.log_evt_success_GetImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_GetImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));

            return FileExist(imagePath) ? (imagePath + "?" + DateTime.Now.Ticks) : string.Empty;
        }
        

        /// <summary>
        /// Gets the image bytes for specified image type and entity id.
        /// If the image does not exist it will return the default 
        /// image's bytes for specified image type
        /// </summary>
        /// <param name="imageType">Image Type</param>
        /// <param name="entityId">Entity Id</param>
        /// <returns>byte array of the image contents</returns>
        public static byte[] GetImageBytes(ImageType imageType, int entityId)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_GetImageBytes, EventStatus.Entry.ToString(), imageType.ToString(), entityId));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_GetImageBytes, EventStatus.Entry.ToString(), imageType.ToString(), entityId));
            string imagePath = GetImageVirtualPath(imageType, entityId);

            if (!FileExist(imagePath))
            {
                imagePath = GetUnknownImagePath(imageType);
            }
            //EventLog.Info(String.Format(Resources.log_evt_success_GetImageBytes, EventStatus.Success.ToString(), imageType.ToString(), entityId));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_GetImageBytes, EventStatus.Success.ToString(), imageType.ToString(), entityId));

            return GetFileBytes(imagePath);
        }

        /// <summary>
        /// Gets the image contents as a Base 64 string for specified image type and entity id.
        /// If the image does not exist it will return empty string
        /// </summary>
        /// <param name="imageType">Image Type</param>
        /// <param name="entityId">Entity Id</param>
        /// <returns>Base 64 string</returns>
        public static string GetImageAsString(ImageType imageType, int entityId)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_GetImageAsString, EventStatus.Entry.ToString(), imageType.ToString(), entityId));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_GetImageAsString, EventStatus.Entry.ToString(), imageType.ToString(), entityId));
            string imagePath = GetImageVirtualPath(imageType, entityId);

            if (FileExist(imagePath))
            {
                return Convert.ToBase64String(GetFileBytes(imagePath));
            }
            //EventLog.Info(String.Format(Resources.log_evt_success_GetImageAsString, EventStatus.Success.ToString(), imageType.ToString(), entityId));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_GetImageAsString, EventStatus.Success.ToString(), imageType.ToString(), entityId));

            return string.Empty;
        }

        /// <summary>
        /// Save the image contents in a the respective folder designated to the image type
        /// </summary>
        /// <param name="imageType">Image Type</param>
        /// <param name="entityId">Entity Id</param>
        /// <param name="fileContents">Image contents as byte array</param>
        public static bool UpdateImage(ImageType imageType, List<ImageFormat> imageFormats, int entityId, byte[] fileContents)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_UpdateImage, EventStatus.Entry.ToString(), imageType.ToString(), entityId));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_UpdateImage, EventStatus.Entry.ToString(), imageType.ToString(), entityId));
            //string imagePath = ""; //GetImageVirtualPath(imageType, entityId);

            /* Checking the file contents are empty */
            if (fileContents != null && fileContents.Length > 0)
            {
                string path = string.Format(IMG_PATH_UP, GetAbsolutePath(), imageType, entityId);
                    //GetAbsolutePath() + imageType + "\\" + entityId + ".jpg";
                if (!string.IsNullOrWhiteSpace(path))
                {
                    string filePath = path; /*HttpContext.Current.Server.MapPath(imagePath);*/ // Getting the physical file path for the virtual path
                    string folderPath = Path.GetDirectoryName(filePath);             // Getting the folder hierarchy from the file path
                    FileStream fileStream = null;

                    /* Checking if folder exists */
                    if (Directory.Exists(folderPath))
                    {
                        /* Checking if image file already exists*/
                        if (File.Exists(filePath))
                        {
                            /* Deleting the already existing file  */
                            File.Delete(filePath);
                        }
                    }
                    else
                    {
                        /* Creating the folder */
                        Directory.CreateDirectory(folderPath);
                    }

                    try
                    {
                        /* Saving the file */
                        using (fileStream = File.Create(filePath))
                        {
                            fileStream.Write(fileContents, 0, fileContents.Length);
                            fileStream.Flush();
                            fileStream.Close();
                        }
                        /* To limit the image width & height*/
                        Image image = System.Drawing.Image.FromFile(filePath);
                        if (!imageFormats.Contains(image.RawFormat))
                        {
                            /* Deleting the uploaded file  */
                            image.Dispose();
                            File.Delete(filePath);
                            //EventLog.Info(String.Format(Resources.log_evt_success_UpdateImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));
                            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_UpdateImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));
                            return false;
                        }
                        if (image.Width > 120 || image.Height > 120)
                        {
                            /* Deleting the uploaded file  */
                            image.Dispose();
                            File.Delete(filePath);
                            //EventLog.Info(String.Format(Resources.log_evt_success_UpdateImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));
                            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_UpdateImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));
                            return false;
                        }
                        else
                        {
                            image.Dispose();
                            //EventLog.Info(String.Format(Resources.log_evt_success_UpdateImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));
                            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_UpdateImage, EventStatus.Success.ToString(), imageType.ToString(), entityId));
                            return true;
                        }

                    }
                    catch (Exception ex)
                    {
                        // log the error
                        //EventLog.Info(String.Format(Resources.log_err_717_UpdateImage, EventStatus.Failure.ToString()) + Resources.err_717);
                        //Logs.WriteLogToDb(String.Format(Resources.log_err_717_UpdateImage, EventStatus.Failure.ToString()) + Resources.err_717);
                        //ErrorLog.Error("717, " + "ERR, " + EventStatus.Failure.ToString() + ", GalleryManager" + ", UpdateImage," + ", " + ex.Message + ", " + ex.InnerException + ", Stack Trace: " + ex.StackTrace);

                        if (fileStream != null)
                        {
                            try
                            {
                                fileStream.Close();
                            }
                            catch
                            { }
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// Deletes the specified image from the Gallery
        /// </summary>
        /// <param name="imagePath"></param>
        public static void DeleteImage(ImageType imageType, int id)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_DeleteImage, EventStatus.Entry.ToString(), imageType.ToString(), id));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_DeleteImage, EventStatus.Entry.ToString(), imageType.ToString(), id));
            string imagePath = GetImageVirtualPath(imageType, id);

            if (HttpContext.Current != null && HttpContext.Current.Server != null)
            {
                // Getting the physical file path for the virtual path
                string filePath = HttpContext.Current.Server.MapPath(imagePath);

                //Deleting the file
                File.Delete(filePath);
            }
            //EventLog.Info(String.Format(Resources.log_evt_success_DeleteImage, EventStatus.Success.ToString(), imageType.ToString(), id));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_DeleteImage, EventStatus.Success.ToString(), imageType.ToString(), id));
        }

        #endregion

        #region Util

        private static string GetImageVirtualPath(ImageType imageType, int id)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_GetImageVirtualPath, EventStatus.Entry.ToString(), imageType.ToString(), id));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_GetImageVirtualPath, EventStatus.Entry.ToString(), imageType.ToString(), id));
            return string.Format(IMAGE_PATH, HttpRuntime.AppDomainAppVirtualPath + ROOT_PATH, imageType.GetName(), id).Replace("//", "/");
        }

        /// <summary>
        /// Gets the Unknown image path
        /// </summary>
        /// <param name="imagePath">image path format to append the root path</param>
        /// <returns>file path to the unknown image </returns>
        private static string GetUnknownImagePath(ImageType imageType)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_GetUnknownImagePath, EventStatus.Entry.ToString(), imageType.ToString()));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_GetUnknownImagePath, EventStatus.Entry.ToString(), imageType.ToString()));
            return string.Format(UNKNOWN_IMAGE_PATH, HttpRuntime.AppDomainAppVirtualPath + ROOT_PATH, imageType.GetName()).Replace("//", "/");
        }

        /// <summary>
        /// Method to check weather file exist in the given location
        /// </summary>
        /// <param name="imagePath"></param>
        /// <returns></returns>
        private static bool FileExist(string imagePath)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_FileExist, EventStatus.Entry.ToString(), imagePath));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_FileExist, EventStatus.Entry.ToString(), imagePath));
            if (HttpContext.Current != null && HttpContext.Current.Server != null)
            {
                return File.Exists(HttpContext.Current.Server.MapPath(imagePath));
            }
            //EventLog.Info(String.Format(Resources.log_evt_success_FileExist, EventStatus.Success.ToString(), imagePath));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_FileExist, EventStatus.Success.ToString(), imagePath));

            return true;
        }

        private static byte[] GetFileBytes(string imagePath)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_GetFileBytes, EventStatus.Entry.ToString(), imagePath));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_GetFileBytes, EventStatus.Entry.ToString(), imagePath));
            if (HttpContext.Current != null && HttpContext.Current.Server != null)
            {
                string physicalPath = HttpContext.Current.Server.MapPath(imagePath);

                if (File.Exists(physicalPath))
                {
                    return File.ReadAllBytes(physicalPath);
                }
            }

            //EventLog.Info(String.Format(Resources.log_evt_success_GetFileBytes, EventStatus.Success.ToString(), imagePath));
            //Logs.WriteLogToDb(String.Format(Resources.log_evt_success_GetFileBytes, EventStatus.Success.ToString(), imagePath));
            return new byte[0];
        }

        private static string GetAbsolutePath()
        {
            return ConfigurationManager.AppSettings["ImageGalleryPath"].ToString();
        }

        #endregion
    }
}